#include "Sensor.h"
#include "Debug.h"
#include "Command_Define.h"

uint8 EventToOffset(uint16 event)
{
	uint8 i = 0;
	
	for(i = 0; i < 16; i++)
	{
		if((event >> i) & 0x0001)
		{
			break;
		}
	}
	return i;
}

//////////////////////////////////////////////////////////
void Sensor_GetEventMsg(Sensor* pSensor, EventReqMsg* pEventReqMsg)
{
    pEventReqMsg->m_EvMRev      = EVENT_MESSAGE_REV;	//Event Message Revision V2.0
	if(SDR_EVENT_ONLY == pSensor->m_pRecodHeader->m_Type)
	{
    	pEventReqMsg->m_SensorType 	= ((EventOnlyRecod*)pSensor->m_pRecodHeader)->m_SensorType;
	}
	else if(SDR_COMPACT_SENSOR == pSensor->m_pRecodHeader->m_Type)
	{
    	pEventReqMsg->m_SensorType 	= ((CompactSensorRecord*)pSensor->m_pRecodHeader)->m_SensorType;
	}
	else if(SDR_FULL_SENSOR == pSensor->m_pRecodHeader->m_Type)
	{
    	pEventReqMsg->m_SensorType 	= ((FullSensorRecord*)pSensor->m_pRecodHeader)->m_SensorType;
	}
	else
	{
		Assert(False);
	}
	
    pEventReqMsg->m_SensorId    = pSensor->m_SensorId;
	memcpy(&pEventReqMsg->m_EventData, &pSensor->m_EventData, sizeof(EventData));
}

uint8 Sensor_Scan(Sensor* pSensor)
{
	return 0;
}

uint8 Sensor_isAlart(Sensor* pSensor)
{
	return pSensor->m_isAlert;
}

Bool Sensor_IsEventMsgEnable(Sensor* pSensor)
{
	return (pSensor->m_isEventMsgEnable == 0);
}

int Sensor_Reset(Sensor* pSensor)
{
	pSensor->m_State 		= 0;
	pSensor->m_isAlert 		= 0;
	pSensor->m_ReadingEvent 	= 0;
	
	pSensor->m_RawValue 	= 0;
	pSensor->m_ReceiverValue 	= 0;
	pSensor->m_HandledValue 	= 0;
	
	memset(&pSensor->m_EventData, 0, sizeof(EventData));
	memset(&pSensor->m_ReceiverEventData, 0, sizeof(EventData));
	
	return 0;
}

void Sensor_Update(Sensor* pSensor, uint8 value, uint8 op)
{
	if(RAW_VALUE == op)
	{
		pSensor->m_RawValue = value;
	}
	else if(REPORTED_VALUE == op)
	{
		pSensor->m_ReceiverValue = value;
	}
	else if(ALL_DATA == op)
	{
		pSensor->m_RawValue = value;
		pSensor->m_ReceiverValue = value;
	}
}

static int Sensor_CrbDone(Sensor* pSensor, Crb* pCrb, uint8 State)
{
	if(CRB_RX_RSP_SUCCESS == State)
	{
		if(0 == pCrb->m_pRspIpmiCmd->m_pCmdData[0])
		{
			EventReqMsg* pEventReqMsg = (EventReqMsg*)pCrb->m_pReqIpmiCmd->m_pCmdData;
			TRACE_LEVEL(TRACE_INTEG_TEST, ("%s, Sensor[%d], Update CmEventData by EventData\n", _FUNC_, pSensor->m_SensorId));
			memcpy(&pSensor->m_ReceiverEventData, &pEventReqMsg->m_EventData, sizeof(EventData));
		}
	}
	
	return ERR_SUCCESS;
}

void Sensor_Changed(void* pCallBackObj, Sensor* pSensor, uint8 newState, uint8 olderState)
{
}

Bool Sensor_Check(Sensor* pSensor, StateChangedFun	Changed, void* pCallBackObj)
{
	if(pSensor->m_RawValue != pSensor->m_HandledValue)
	{
		if(Changed)
		{
			if(ERR_SUCCESS == Changed(pCallBackObj, pSensor, pSensor->m_RawValue, pSensor->m_HandledValue))
			{
				pSensor->m_HandledValue = pSensor->m_RawValue;
			}
		}
		return True;
	}
	
	return False;
}

Bool Sensor_IsChangedEx(Sensor* pSensor)
{
	if(pSensor->m_RawValue == pSensor->m_ReceiverValue) return False;

	pSensor->GetEventData(pSensor);
	if(memcmp(&pSensor->m_EventData, &pSensor->m_ReceiverEventData, sizeof(EventData)) == 0) 
	{
		pSensor->m_ReceiverValue = pSensor->m_RawValue;
		TRACE_LEVEL(TRACE_INTEG_TEST, ("%s,Sensor[%d], CmRawValue=%d\n", _FUNC_, pSensor->m_SensorId, pSensor->m_ReceiverValue));
		return False;
	}
	else
	{
		return True;
	}
}

int Sensor_SendEventMsg(Sensor* pSensor)
{
	static ReqData req =
	{
		PLATFORM_EVENT_MESSAGE, NETFUN_SSEVENT_REQ, CMD_EVENT_LUN, 0, (CrbNotifyFun)Sensor_CrbDone, Null, sizeof(EventReqMsg)
	};

	Crb* pCrb = pSensor->m_pCrb;
	//IpmiHeader* pHeader = &pCrb->m_pReqIpmiCmd->m_Header;

	if(pCrb && pSensor->m_isEventMsgEnable && Crb_isIdle(pCrb))
	{
		if(Sensor_IsChangedEx(pSensor))
		{			
			Assert(REQ_DATA_SIZE >= req.m_len);
			TRACE_LEVEL(TRACE_SENSOR | TRACE_INTEG_TEST, ("%s Sensor[%d] send EVENT MSG[%d].\n", pSensor->m_IdString, pSensor->m_SensorId, pSensor->m_EventData.m_EventData1.m_Offset));
			
			req.m_pRequester = pSensor;
			Sensor_GetEventMsg(pSensor, (EventReqMsg*)&req.m_buff);
			
			Crb_SendReq(pCrb, &req);
			return ERR_SUCCESS;
		}
	}
	
	return ERR_FAILED;
}

void Sensor_GetEventData(Sensor* pSensor)
{
	EventData* pEventData = &pSensor->m_EventData;

    pEventData->m_EventDir  	= EVENT_ASSERTION;
	if(SDR_EVENT_ONLY == pSensor->m_pRecodHeader->m_Type)
	{
    	pEventData->m_EventType 	= ((EventOnlyRecod*)pSensor->m_pRecodHeader)->m_EventType;
	}
	else if(SDR_COMPACT_SENSOR == pSensor->m_pRecodHeader->m_Type)
	{
    	pEventData->m_EventType 	= ((CompactSensorRecord*)pSensor->m_pRecodHeader)->m_EventType;
	}
	else if(SDR_FULL_SENSOR == pSensor->m_pRecodHeader->m_Type)
	{
    	pEventData->m_EventType 	= ((FullSensorRecord*)pSensor->m_pRecodHeader)->m_EventType;
	}
	else
	{
		Assert(False);
	}

    pEventData->m_EventData1.m_Offset 		= pSensor->m_RawValue;
    pEventData->m_EventData1.m_Data2Format 	= 0;
    pEventData->m_EventData1.m_Data3Format 	= 0;
    pEventData->m_EventData2	= 0xFF;
    pEventData->m_EventData3	= 0xFF;

	pSensor->m_ReadingEvent = pSensor->m_RawValue;
}


void Sensor_Init(Sensor* pSensor
	, SdrHeader* 		pSdrHeader
	, uint8 			shareId	//0 = not share record,  > 0 = share reccode
	, SensorFun			Scan
	, GetEventDataFun	GetEventData
	, Crb*				pCrb
	, void* 			pCallBackObj
	, uint8 			defaultValue
	)
{
	memset(pSensor, 0, sizeof(Sensor));

	pSensor->m_isValid = 1;
	if(SDR_EVENT_ONLY == pSdrHeader->m_Type)
	{
		EventOnlyRecod* pRecod = ((EventOnlyRecod*)pSdrHeader);
		pSensor->m_SensorId = shareId + pRecod->m_SensorNumber;
		memcpy(pSensor->m_IdString, pRecod->m_IdString, pRecod->m_IdStrLen);
	}
	else if(SDR_COMPACT_SENSOR == pSdrHeader->m_Type)
	{
		CompactSensorRecord* pRecod = ((CompactSensorRecord*)pSdrHeader);
		pSensor->m_SensorId = shareId + pRecod->m_SensorNumber;
		memcpy(pSensor->m_IdString, pRecod->m_IdString, pRecod->m_IdStrLen);
	}
	else if(SDR_FULL_SENSOR == pSdrHeader->m_Type)
	{
		FullSensorRecord* pRecod = ((FullSensorRecord*)pSdrHeader);
		pSensor->m_SensorId = shareId + pRecod->m_SensorNumber;
		memcpy(pSensor->m_IdString, pRecod->m_IdString, pRecod->m_IdStrLen);
	}
	else
	{
		Assert(False);
	}
	TRACE_LEVEL(TRACE_SENSOR|TRACE_MAIN, ("Sensor %s[%d] Init, type=%x\n", pSensor->m_IdString, pSensor->m_SensorId, pSdrHeader->m_Type));
	
	if(shareId)
	{
		pSensor->m_isShare = True;
	}

	pSensor->m_pRecodHeader = pSdrHeader;
	pSensor->m_pCrb = pCrb;

	pSensor->Reset = (SensorFun)Sensor_Reset;
	pSensor->Scan = Scan;
	pSensor->GetEventData = GetEventData;

	pSensor->m_pCallBackObj = pCallBackObj;
	
	pSensor->m_isEventMsgEnable = 0;
	pSensor->m_isScanEnable = 1;
	pSensor->m_DefaultValue = defaultValue;	
}

Sensor* Sensor_New(Sensor sensor[], uint8 sensorCount)
{
	int i = 0;
	Sensor* pSensor = Null;

	pSensor = sensor;
	for(i = 0; i < sensorCount; i++,pSensor++)
	{
		if(!pSensor->m_isValid)
		{
			return pSensor;
		}
	}

	Trace("Warning: %s() No Space\n");
	return Null;
}

//////////////////////////////////////////////////////////

